package com.wlyuan.open.domain.source.dispatcher.conversion;

import com.wlyuan.core.exception.AssertUtils;
import com.wlyuan.core.exception.ValueError;
import com.wlyuan.open.constants.CarrierTypeEnum;
import com.wlyuan.open.constants.CustomerTypeEnum;
import com.wlyuan.open.domain.source.dispatcher.consignee.CreateConsignee;
import com.wlyuan.open.domain.source.dispatcher.customer.CreateCustomer;
import com.wlyuan.open.domain.source.repository.cache.OpenDriverCacheRepository;
import com.wlyuan.open.domain.source.repository.cache.OpenDriverVehicleRepository;
import com.wlyuan.open.domain.source.repository.cache.OpenOrderCacheRepository;
import com.wlyuan.open.dto.OpenTransportSyncDTO;
import com.wlyuan.open.dto.transport.TransportAttachDTO;
import com.wlyuan.open.dto.transport.TransportReceiptDTO;
import com.wlyuan.open.dto.transport.TransportSignDTO;
import com.wlyuan.open.remote.facade.AddressDTO;
import com.wlyuan.open.remote.facade.CustomerFacade;
import com.wlyuan.open.remote.facade.GoodsFacade;
import com.wlyuan.open.remote.facade.constants.Constants;
import com.wlyuan.open.utils.LongUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Optional;

/**
 * @author lijing
 * @description
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class OpenDispatcherTransportConversion implements OpenDispatcherConversion<OpenTransportSyncDTO> {
    private final BaseOpenDispatcherConversion baseOpenDispatcherConversion;
    private final OpenOrderCacheRepository openOrderCacheRepository;
    private final OpenDriverCacheRepository openDriverCacheRepository;
    private final OpenDriverVehicleRepository openDriverVehicleRepository;
    private final GoodsFacade goodsFacade;
    private final CustomerFacade customerFacade;

    @Override
    public void convert(OpenTransportSyncDTO source) {
        //租户转换
        tenantConvert(source);
        //信息转换
        infoConvert(source);
        //上游
        carrierConvert(source);
        //下游
        customerConvert(source);
        //物品id转换
        goodsConvert(source);
        //合约
        templateConvert(source);
        //地区
        areaConvert(source);
    }

    private void tenantConvert(OpenTransportSyncDTO source) {
        var tenant = source.getTenantId();
        if (LongUtils.notNullLong(tenant)) {
            var tenantId = baseOpenDispatcherConversion.tenant(tenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("OpenTransportSyncDTO租户不存在:" + tenant), source);
            source.setTenantId(tenantId);
        }
        var orderTenant = source.getOrderTenantId();
        if (LongUtils.notNullLong(orderTenant)) {
            var tenantId = baseOpenDispatcherConversion.tenant(orderTenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("OpenTransportSyncDTO 订单租户不存在:" + orderTenant), source);
            source.setOrderTenantId(tenantId);
        }
    }

    private void infoConvert(OpenTransportSyncDTO source) {
        //上游运单id
        var upTransport = source.getSourceWaybillId();
        if (LongUtils.notNullLong(upTransport)) {
            var upTransportId = baseOpenDispatcherConversion.transport(upTransport);
            AssertUtils.assertNotNull(upTransportId, new ValueError("OpenTransportSyncDTO上游运单不存在:" + upTransport), source);
            source.setSourceWaybillId(upTransportId);
        }
        //订单id
        var oId = source.getOrderId();
        if (LongUtils.notNullLong(oId)) {
            var orderId = openOrderCacheRepository.convert(oId);
            AssertUtils.assertNotNull(orderId, new ValueError("OpenTransportSyncDTO订单不存在:" + oId), source);
            source.setOrderId(orderId);
        }
        //创建人
        var crId = source.getCreateBy();
        if (LongUtils.notNullLong(crId)) {
            var create = baseOpenDispatcherConversion.user(crId);
            AssertUtils.assertNotNull(create, new ValueError("OpenTransportSyncDTO制单人不存在:" + crId), source);
            source.setCreateBy(create);
        }
        //修改人
        var upId = source.getUpdateBy();
        if (LongUtils.notNullLong(upId)) {
            var update = baseOpenDispatcherConversion.user(upId);
            AssertUtils.assertNotNull(update, new ValueError("OpenTransportSyncDTO修改人不存在:" + upId), source);
            source.setUpdateBy(update);
        }
        //调度人
        var did = source.getDispatchBy();
        if (LongUtils.notNullLong(did)) {
            var dispatchId = baseOpenDispatcherConversion.user(did);
            AssertUtils.assertNotNull(dispatchId, new ValueError("OpenTransportSyncDTO调度人不存在:" + did), source);
            source.setDispatchBy(dispatchId);
        }
        //订单创建人
        var orId = source.getOrderCreateBy();
        if (LongUtils.notNullLong(orId)) {
            var userId = baseOpenDispatcherConversion.user(orId);
            AssertUtils.assertNotNull(userId, new ValueError("OpenTransportSyncDTO订单创建人不存在:" + orId), source);
            source.setOrderCreateBy(userId);
        }

        //客户
        if (LongUtils.notNullLong(source.getCustomerId())) {
            var customer = baseOpenDispatcherConversion.customer(source.getCustomerId(), source.getCustomerType(), source.getTenantId());
            AssertUtils.assertNotNull(customer, new ValueError("OpenTransportSyncDTO 客户不存在:" + source.getCustomerId() + "," + source.getCustomerType() + "," + source.getTenantId()), source);
            source.setCustomerId(customer.getCustomerId());
            if (StringUtils.isNotBlank(customer.getCustomerName())) {
                source.setCustomerName(customer.getCustomerName());
            }
        } else {
            //为空或者0 , 创建线下客户
            var customer = customerFacade.createCustomer(new CreateCustomer(source.getCustomerName(), source.getFromAddress().getContactMobile(), source.getFromAddress().getContactName(), source.getTenantId(), source.getCreateBy()));
            source.setCustomerId(customer.getCustomerId());
            source.setCustomerName(customer.getName());
        }

        //订单客户
        if (LongUtils.notNullLong(source.getOrderCustomerId())) {
            var customer = baseOpenDispatcherConversion.customer(source.getOrderCustomerId(), source.getOrderCustomerType(), source.getOrderTenantId());
            AssertUtils.assertNotNull(customer, new ValueError("OpenTransportSyncDTO 客户不存在:" + source.getCustomerId() + "," + source.getCustomerType() + "," + source.getTenantId()), source);
            source.setOrderCustomerId(customer.getCustomerId());
            if (StringUtils.isNotBlank(customer.getCustomerName())) {
                source.setOrderCustomerName(customer.getCustomerName());
            }
        } else {
            //为空或者0 , 创建线下客户
            var customer = customerFacade.createCustomer(new CreateCustomer(source.getOrderCustomerName(), source.getFromAddress().getContactMobile(), source.getFromAddress().getContactName(), source.getOrderTenantId(), source.getOrderCreateBy()));
            source.setOrderCustomerId(customer.getCustomerId());
            source.setOrderCustomerName(customer.getName());
        }

        //关单
        close(source);

    }

    private void goodsConvert(OpenTransportSyncDTO source) {
        if (CollectionUtils.isEmpty(source.getGoodsList())) {
            return;
        }
        source.getGoodsList().forEach(orderGoodsDTO -> {
            //创建物品
            var goods = goodsFacade.createGoods(orderGoodsDTO, source.getOrderCustomerId(), source.getOrderTenantId(), source.getOrderCreateBy());
            orderGoodsDTO.setGoodsId(goods.getGoodsId());
        });
        baseOpenDispatcherConversion.generateBatchNo(source.getGoodsList());

    }

    private void carrierConvert(OpenTransportSyncDTO source) {
        Optional.ofNullable(source.getCarrier()).ifPresent(carrier -> {
            //租户
            var tenant = carrier.getTenantId();
            var tenantId = baseOpenDispatcherConversion.tenant(tenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("OpenTransportSyncDTO carrier 租户不存在:" + tenant), source);
            carrier.setTenantId(tenantId);
            //承运方
            var carrierId = carrier.getCarrierId();
            var carrierType = carrier.getCarrierType();
            //承运方类型为自己/自营时，承运方id为空
            if (LongUtils.notNullLong(carrierId) || CarrierTypeEnum.isMyself(carrierType) || CarrierTypeEnum.isDriver(carrierType)) {
                var supplier = baseOpenDispatcherConversion.carrier(carrierId, carrierType, carrier.getTenantId());
                AssertUtils.assertNotNull(supplier, new ValueError("OpenTransportSyncDTO承运方不存在:" + carrierId + "," + carrierType + "," + carrier.getTenantId()), source);
                carrier.setCarrierId(supplier.getCarrierId());
                carrier.setCarrierType(supplier.getCarrierType());
                if (StringUtils.isNotBlank(supplier.getCarrierContactName())) {
                    carrier.setContactName(supplier.getCarrierContactName());
                }
                if (StringUtils.isNotBlank(supplier.getCarrierPhone())) {
                    carrier.setContactMobile(supplier.getCarrierPhone());
                }
                if (StringUtils.isNoneBlank(supplier.getCarrierName())) {
                    carrier.setCarrierName(supplier.getCarrierName());
                }
            }
            //司机id
            if (LongUtils.notNullLong(carrier.getDriverId())) {
                var driver = openDriverCacheRepository.convert(carrier.getDriverId());
                AssertUtils.assertNotNull(driver, new ValueError("OpenTransportSyncDTO司机不存在:" + carrier.getDriverId()), source);
                carrier.setDriverId(driver);
            }
            //车辆id
            if (LongUtils.notNullLong(carrier.getVehicleId())) {
                var vehicle = openDriverVehicleRepository.convert(carrier.getVehicleId());
                AssertUtils.assertNotNull(vehicle, new ValueError("OpenTransportSyncDTO车辆不存在:" + carrier.getVehicleId()), source);
                carrier.setVehicleId(vehicle);
            }

            //签收
            sign(carrier.getSign(), source);
            //回单
            receipt(carrier.getReceipt(), source);
            //附件
            attachConvert(carrier.getAttachments());
        });
    }

    private void customerConvert(OpenTransportSyncDTO source) {
        Optional.ofNullable(source.getCustomer()).ifPresent(customerInfo -> {
            //租户
            var tenant = customerInfo.getTenantId();
            var tenantId = baseOpenDispatcherConversion.tenant(tenant);
            AssertUtils.assertNotNull(tenantId, new ValueError("OpenTransportSyncDTO customer 租户不存在:" + tenant), source);
            customerInfo.setTenantId(tenantId);
            //客户
            var cId = customerInfo.getCustomerId();
            if (LongUtils.notNullLong(cId) || CustomerTypeEnum.MYSELF.getValue().equals(customerInfo.getCustomerType())) {
                var customer = baseOpenDispatcherConversion.customer(cId, customerInfo.getCustomerType(), tenantId);
                logger.info("OpenTransportSyncDTO 客户信息：{}", customer);
                AssertUtils.assertNotNull(customer, new ValueError("运单客户不存在:" + cId + "," + customerInfo.getCustomerType() + "," + tenantId), customerInfo);
                customerInfo.setCustomerId(customer.getCustomerId());
                if (StringUtils.isNotBlank(customer.getCustomerName())) {
                    customerInfo.setCustomerName(customer.getCustomerName());
                }
            }
            //签收
            sign(customerInfo.getSign(), source);
            //回单
            receipt(customerInfo.getReceipt(), source);
            //附件
            attachConvert(customerInfo.getAttachments());
        });
    }

    private void close(OpenTransportSyncDTO source) {
        var close = source.getClose();
        Optional.ofNullable(close).ifPresent(c -> {
            //关单人
            var clId = c.getCloseBy();
            if (LongUtils.notNullLong(clId)) {
                var closeId = baseOpenDispatcherConversion.user(clId);
                AssertUtils.assertNotNull(closeId, new ValueError("OpenTransportSyncDTO关单操作人不存在:" + clId), close);
                c.setCloseBy(closeId);
            }
            //关单审核租户
            var tenant = c.getToTenantId();
            if (LongUtils.notNullLong(tenant)) {
                var tenantId = baseOpenDispatcherConversion.tenant(tenant);
                AssertUtils.assertNotNull(tenantId, new ValueError("OpenTransportSyncDTO关单审核租户不存在:" + tenant), source);
                c.setToTenantId(tenantId);
            }
        });
    }

    private void sign(TransportSignDTO sign, OpenTransportSyncDTO source) {
        Optional.ofNullable(sign).ifPresent(s -> {
            //签收人
            var sId = s.getSignBy();
            if (LongUtils.notNullLong(sId)) {
                var userId = baseOpenDispatcherConversion.user(sId);
                AssertUtils.assertNotNull(userId, new ValueError("OpenTransportSyncDTO签单人不存在:" + sId), sign);
                s.setSignBy(userId);
            }
            //签收物品
            var goodsSign = s.getSigns();
            if (!CollectionUtils.isEmpty(goodsSign)) {
                goodsSign.forEach(g -> {
                    //创建物品
                    var goods = goodsFacade.createGoods(g, source.getOrderCustomerId(), source.getOrderTenantId(), source.getOrderCreateBy());
                    g.setGoodsId(goods.getGoodsId());
                });
                baseOpenDispatcherConversion.generateBatchNo(goodsSign);
                s.setSigns(goodsSign);
            }
        });
    }

    private void receipt(TransportReceiptDTO receipt, OpenTransportSyncDTO source) {
        Optional.ofNullable(receipt).ifPresent(r -> {
            //回单人
            var rId = r.getReceiptBy();
            if (LongUtils.notNullLong(rId)) {
                var userId = baseOpenDispatcherConversion.user(rId);
                AssertUtils.assertNotNull(userId, new ValueError("OpenTransportSyncDTO回单人不存在:" + rId), receipt);
                r.setReceiptBy(userId);
            }
            //回单物品
            var goodsReceipt = r.getReceipts();
            if (!CollectionUtils.isEmpty(goodsReceipt)) {
                goodsReceipt.forEach(g -> {
                    //创建物品
                    var goods = goodsFacade.createGoods(g, source.getOrderCustomerId(), source.getOrderTenantId(), source.getOrderCreateBy());
                    g.setGoodsId(goods.getGoodsId());
                });
                baseOpenDispatcherConversion.generateBatchNo(goodsReceipt);
                r.setReceipts(goodsReceipt);
            }
        });
    }

    private void attachConvert(List<TransportAttachDTO> attachList) {
        if (!CollectionUtils.isEmpty(attachList)) {
            attachList.forEach(a -> {
                if (LongUtils.notNullLong(a.getCreateBy())) {
                    var createBy = baseOpenDispatcherConversion.user(a.getCreateBy());
                    AssertUtils.assertNotNull(createBy, new ValueError("OpenTransportSyncDTO 附件创建人不存在:" + a.getCreateBy()), attachList);
                    a.setCreateBy(createBy);
                }
            });
        }
    }

    private void templateConvert(OpenTransportSyncDTO source) {
        Optional.ofNullable(source.getQuote()).ifPresent(quote -> {
            if (LongUtils.notNullLong(quote.getTemplateId())) {
                var templateId = baseOpenDispatcherConversion.template(quote.getTemplateId());
                AssertUtils.assertNotNull(templateId, new ValueError("OpenTransportSyncDTO 合约不存在:" + quote.getTemplateId()), source);
                quote.setTemplateId(templateId);
            }
        });
    }

    private void areaConvert(OpenTransportSyncDTO source) {
        Optional.ofNullable(source.getFromAddress()).ifPresent(f -> {
            if (StringUtils.isNotBlank(f.getProvince()) || StringUtils.isNotBlank(f.getCity()) || StringUtils.isNotBlank(f.getDistrict()) || StringUtils.isNotBlank(f.getAddress())) {
                var area = baseOpenDispatcherConversion.area(new AddressDTO(f.getProvinceCode(), f.getProvince(), f.getCityCode(), f.getCity(), f.getDistrictCode(), f.getDistrict(), f.getAddress(), Constants.LEVEL));
                AssertUtils.assertNotNull(area, new ValueError("OpenTransportSyncDTO 发货地址不存在:" + f.getProvince() + "," + f.getCity() + "," + f.getDistrict() + "," + f.getAddress()), source);
                f.setProvinceCode(area.getProvinceCode());
                f.setProvince(area.getProvinceName());
                f.setCityCode(area.getCityCode());
                f.setCity(area.getCityName());
                f.setDistrictCode(area.getDistrictCode());
                f.setDistrict(area.getDistrictName());
                if (StringUtils.isBlank(f.getLocation()) && StringUtils.isNotBlank(area.getLat()) && StringUtils.isNotBlank(area.getLon())) {
                    f.setLocation(area.getLat() + "," + area.getLon());
                }
                if (StringUtils.isBlank(f.getAddress())) {
                    f.setAddress("#");
                }
            }
        });

        Optional.ofNullable(source.getToAddress()).ifPresent(t -> {
            if (StringUtils.isNotBlank(t.getProvince()) || StringUtils.isNotBlank(t.getCity()) || StringUtils.isNotBlank(t.getDistrict()) || StringUtils.isNotBlank(t.getAddress())) {
                var area = baseOpenDispatcherConversion.area(new AddressDTO(t.getProvinceCode(), t.getProvince(), t.getCityCode(), t.getCity(), t.getDistrictCode(), t.getDistrict(), t.getAddress(), Constants.LEVEL));
                AssertUtils.assertNotNull(area, new ValueError("OpenTransportSyncDTO 收货地址不存在:" + t.getProvince() + "," + t.getCity() + "," + t.getDistrict() + "," + t.getAddress()), source);
                t.setProvinceCode(area.getProvinceCode());
                t.setProvince(area.getProvinceName());
                t.setCityCode(area.getCityCode());
                t.setCity(area.getCityName());
                t.setDistrictCode(area.getDistrictCode());
                t.setDistrict(area.getDistrictName());
                if (StringUtils.isBlank(t.getLocation()) && StringUtils.isNotBlank(area.getLat()) && StringUtils.isNotBlank(area.getLon())) {
                    t.setLocation(area.getLat() + "," + area.getLon());
                }
                if (StringUtils.isBlank(t.getAddress())) {
                    t.setAddress("#");
                }
            }

            //收货方id
            var create = new CreateConsignee(source.getConsigneeName(), t.getContactMobile(), t.getContactName(),
                    source.getOrderCustomerId(), source.getOrderCustomerName(), source.getOrderTenantId(), source.getOrderCreateBy());
            var consignee = baseOpenDispatcherConversion.consignee(create);
            source.setConsigneeId(consignee.getConsigneeId());
        });
    }
}
